`timescale 1 ns / 1 ps

module axi_lvds_v1_0 #(
  // Users to add parameters here

  parameter   FPGA_TECHNOLOGY = 1,
  parameter   IODELAY_ENABLE = 0,
  parameter   IODELAY_ENABLE_RX = 0,
  parameter   IO_DELAY_GROUP = "line_delay",
  parameter   IODELAY_CTRL = 0,
  parameter   CLK_DESKEW = 0,
  parameter   USE_MCLK = 1,
  parameter   USE_CLK_DELAY =0,
  parameter   DELAY_REFCLK_FREQUENCY = 100,
  parameter   USE_TX_CLKSEL =0,
  parameter integer C_S_AXI_ADDR_WIDTH	= 5

) (
  // Users to add ports here

  // User ports ends
  // Do not modify the ports beyond this line
  

  // Ports of Axi Slave Bus Interface S00_AXI
  input wire  s00_axi_aclk,
  input wire  s00_axi_aresetn,
  input wire [C_S_AXI_ADDR_WIDTH-1 : 0] s00_axi_awaddr,
  input wire [2 : 0] s00_axi_awprot,
  input wire  s00_axi_awvalid,
  output wire  s00_axi_awready,
  input wire [31: 0] s00_axi_wdata,
  input wire [(32/8)-1 : 0] s00_axi_wstrb,
  input wire  s00_axi_wvalid,
  output wire  s00_axi_wready,
  output wire [1 : 0] s00_axi_bresp,
  output wire  s00_axi_bvalid,
  input wire  s00_axi_bready,
  input wire [C_S_AXI_ADDR_WIDTH-1 : 0] s00_axi_araddr,
  input wire [2 : 0] s00_axi_arprot,
  input wire  s00_axi_arvalid,
  output wire  s00_axi_arready,
  output wire [31: 0] s00_axi_rdata,
  output wire [1 : 0] s00_axi_rresp,
  output wire  s00_axi_rvalid,
  input wire  s00_axi_rready,

  // LVDS interface ports
  // physical interface (receive)
  input               rx_clk_in_p,
  input               rx_clk_in_n,
  input               rx_frame_in_p,
  input               rx_frame_in_n,
  input   [ 5:0]      rx_data_in_p,
  input   [ 5:0]      rx_data_in_n,

  // physical interface (transmit)
  output              tx_clk_out_p,
  output              tx_clk_out_n,
  output              tx_frame_out_p,
  output              tx_frame_out_n,
  output  [ 5:0]      tx_data_out_p,
  output  [ 5:0]      tx_data_out_n,

  // clock (common to both receive and transmit)
  input               rst_n,
  input               skew_clk,//used to skew or replace m_clk
  output              m_clk,  //pin clock

  // receive data path interface
  output              adc_valid,
  output  [47:0]      adc_data,
  output              adc_status,
  input               adc_r1_mode,

  // transmit data path interface
  input               dac_valid,
  input   [47:0]      dac_data,
  input               dac_clk_inv,
  input               dac_r1_mode,

    // delay interface
  input               up_clk, //used to load delay value
  input   delay_clk,//used to product delay ,always 200Mhz
  input               delay_rstn,
  output              delay_locked
);
  
  // AXI-Lite signals (internal)
  wire [31: 0] slv_reg0_data;
  wire [31: 0] slv_reg1_data;
  wire [31: 0] slv_reg2_data;
  wire [31: 0] slv_reg3_data;
  wire [31: 0] slv_reg4_data;
  wire [31: 0] slv_reg5_data;
  wire [31: 0] slv_reg6_data;

  // Instantiation of Axi Bus Interface S00_AXI
  axi_lvds_v1_0_S00_AXI axi_lvds_v1_0_S00_AXI_inst (
    .S_AXI_ACLK(s00_axi_aclk),
    .S_AXI_ARESETN(s00_axi_aresetn),
    .S_AXI_AWADDR(s00_axi_awaddr),
    .S_AXI_AWPROT(s00_axi_awprot),
    .S_AXI_AWVALID(s00_axi_awvalid),
    .S_AXI_AWREADY(s00_axi_awready),
    .S_AXI_WDATA(s00_axi_wdata),
    .S_AXI_WSTRB(s00_axi_wstrb),
    .S_AXI_WVALID(s00_axi_wvalid),
    .S_AXI_WREADY(s00_axi_wready),
    .S_AXI_BRESP(s00_axi_bresp),
    .S_AXI_BVALID(s00_axi_bvalid),
    .S_AXI_BREADY(s00_axi_bready),
    .S_AXI_ARADDR(s00_axi_araddr),
    .S_AXI_ARPROT(s00_axi_arprot),
    .S_AXI_ARVALID(s00_axi_arvalid),
    .S_AXI_ARREADY(s00_axi_arready),
    .S_AXI_RDATA(s00_axi_rdata),
    .S_AXI_RRESP(s00_axi_rresp),
    .S_AXI_RVALID(s00_axi_rvalid),
    .S_AXI_RREADY(s00_axi_rready),
    // Pass slave registers to be used inside AXI module
    .reg0(slv_reg0_data),
    .reg1(slv_reg1_data),
    .reg2(slv_reg2_data),
    .reg3(slv_reg3_data),
    .reg4(slv_reg4_data),
    .reg5(slv_reg5_data),
    .reg6(slv_reg6_data),
    .reg7()
  );

  // Instantiation of LVDS interface
  lvds #(
    .FPGA_TECHNOLOGY(FPGA_TECHNOLOGY),
    .IODELAY_ENABLE(IODELAY_ENABLE),
    .IODELAY_ENABLE_RX(IODELAY_ENABLE_RX),
    .IO_DELAY_GROUP(IO_DELAY_GROUP),
    .IODELAY_CTRL(IODELAY_CTRL),
    .CLK_DESKEW(CLK_DESKEW),
    .USE_MCLK(USE_MCLK),
    .USE_CLK_DELAY(USE_CLK_DELAY),
    .DELAY_REFCLK_FREQUENCY(DELAY_REFCLK_FREQUENCY),
    .USE_TX_CLKSEL(USE_TX_CLKSEL)
  ) lvds_inst (
    // physical interface (receive)
    .rx_clk_in_p(rx_clk_in_p),
    .rx_clk_in_n(rx_clk_in_n),
    .rx_frame_in_p(rx_frame_in_p),
    .rx_frame_in_n(rx_frame_in_n),
    .rx_data_in_p(rx_data_in_p),
    .rx_data_in_n(rx_data_in_n),

    // physical interface (transmit)
    .tx_clk_out_p(tx_clk_out_p),
    .tx_clk_out_n(tx_clk_out_n),
    .tx_frame_out_p(tx_frame_out_p),
    .tx_frame_out_n(tx_frame_out_n),
    .tx_data_out_p(tx_data_out_p),
    .tx_data_out_n(tx_data_out_n),

    // clock (common to both receive and transmit)
    .rst_n(rst_n),
    .skew_clk(skew_clk),
    .m_clk(m_clk),

    // receive data path interface
    .adc_valid(adc_valid),
    .adc_data(adc_data),
    .adc_status(adc_status),
    .adc_r1_mode(adc_r1_mode),

    // transmit data path interface
    .dac_valid(dac_valid),
    .dac_data(dac_data),
    .dac_clk_inv(dac_clk_inv),
    .dac_r1_mode(dac_r1_mode),

    // delay interface
    .up_clk(up_clk), //used to load delay value
    .up_adc_dld(slv_reg1_data[ 6:0]),
    .up_adc_dwdata({slv_reg2_data[2:0],slv_reg3_data[31:0]}),
    .up_adc_drdata( ),
    .up_dac_dld(slv_reg4_data[ 9:0]),
    .up_dac_dwdata({slv_reg5_data[17:0],slv_reg6_data[31:0]}),
    .up_dac_drdata( ),
    .delay_clk(delay_clk),//used to product delay ,always 200Mhz
    .delay_rstn(delay_rstn),
    .delay_locked(delay_locked)
  );

endmodule